package cn.xyz.mianshi.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.codec.digest.DigestUtils;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.query.Query;
import org.mongodb.morphia.query.UpdateOperations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.collect.Maps;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.shiku.lbs.service.NearbyManager;
import com.shiku.lbs.vo.NearbyUser;

import cn.xyz.commons.autoconfigure.KApplicationProperties.XMPPConfig;
import cn.xyz.commons.constants.KConstants;
import cn.xyz.commons.constants.KKeyConstant;
import cn.xyz.commons.ex.ServiceException;
import cn.xyz.commons.support.jedis.JedisCallback;
import cn.xyz.commons.support.jedis.JedisCallbackVoid;
import cn.xyz.commons.utils.DateUtil;
import cn.xyz.commons.utils.StringUtil;
import cn.xyz.mianshi.example.UserExample;
import cn.xyz.mianshi.example.UserQueryExample;
import cn.xyz.mianshi.service.CompanyManager;
import cn.xyz.mianshi.service.FriendsManager;
import cn.xyz.mianshi.service.IdxManager;
import cn.xyz.mianshi.service.UserManager;
import cn.xyz.mianshi.utils.KSessionUtil;
import cn.xyz.mianshi.vo.Friends;
import cn.xyz.mianshi.vo.User;
import cn.xyz.repository.UserRepository;
import cn.xyz.service.KSMSServiceImpl;
import cn.xyz.service.KXMPPServiceImpl;
import redis.clients.jedis.Jedis;

@Service(UserManagerImpl.BEAN_ID)
public class UserManagerImpl extends MongoRepository<User, Integer> implements UserManager {
	public static final String BEAN_ID = "UserManagerImpl";

	@Autowired
	private CompanyManager companyManager;
	@Autowired
	private FriendsManager friendsManager;
	@Autowired
	private IdxManager idxManager;
	@Autowired
	private NearbyManager nearbyManager;
	
	@Autowired
	private KSMSServiceImpl smsService;

	@Autowired
	private UserRepository userRepository;
	
	@Resource(name = "dsForTigase")
	private Datastore dsForTigase;
	@Resource(name = "xmppConfig")
	private XMPPConfig xmppConfig;

	@Override
	public User createUser(String telephone, String password) {
		User user = new User();
		user.setUserId(idxManager.getUserId());
		user.setUserKey(DigestUtils.md5Hex(telephone));
		user.setPassword(DigestUtils.md5Hex(password));
		user.setTelephone(telephone);

		userRepository.addUser(user);

		return user;
	}

	@Override
	public void createUser(User user) {
		userRepository.addUser(user);

	}

	@Override
	public User.UserSettings getSettings(int userId) {
		return userRepository.getSettings(userId);
	}

	@Override
	public User getUser(int userId) {
		//先从 Redis 缓存中获取
		User user =KSessionUtil.getUserByUserId(userId);
		if(null==user){
				user = userRepository.getUser(userId);
			if (null == user)
				throw new ServiceException("用户不存在");
			if (0 != user.getCompanyId())
				user.setCompany(companyManager.get(user.getCompanyId()));
			KSessionUtil.saveUserByUserId(userId, user);
		}
		
		return user;
	}

	@Override
	public User getUser(int userId, int toUserId) {
		User user = getUser(toUserId);

		Friends friends = friendsManager.getFriends(new Friends(userId, toUserId));
		user.setFriends(null == friends ? null : friends);

		// if (userId == toUserId) {
		// List<ResumeV2> resumeList = resumeManager.selectByUserId(toUserId);
		// user.setResumeList(resumeList);
		// }

		return user;
	}
	
	//此接口用于根据studentId,teacherId 查找学生数据
	@Override
	public User getUserByStuIdAndTeacId(int studentId, int teacherId) {
		Query<User> q = dsForRW.createQuery(User.class).field("studentId").equal(studentId).field("teacherId").equal(teacherId);
		return q.get();
	}
	
	

	@Override
	public User getUser(String telephone) {
		//Integer userId=KSessionUtil.getUserIdByTelephone(telephone);
		
		return userRepository.getUser(telephone);
	}

	@Override
	public int getUserId(String accessToken) {
		return 0;
	}

	@Override
	public boolean isRegister(String telephone) {
		return 1 == userRepository.getCount(telephone);
	}

	@Override
	public User login(String telephone, String password) {
		String userKey = DigestUtils.md5Hex(telephone);

		User user = userRepository.getUserv1(userKey,0, null);

		if (null == user) {
			throw new ServiceException("帐号不存在");
		} else {
			String _md5 = DigestUtils.md5Hex(password);
			String _md5_md5 = DigestUtils.md5Hex(_md5);

			if (_md5.equals(user.getPassword()) || _md5_md5.equals(user.getPassword())) {
				return user;
			} else {
				throw new ServiceException("帐号或密码错误");
			}
		}
	}

	@Override
	public Map<String, Object> login(UserExample example) {
		User user = userRepository.getUser(example.getAreaCode(),example.getTelephone(), null);
		if (null == user) {
			throw new ServiceException(1040101, "帐号不存在, 请重新注册!");
		} else {
			String password = example.getPassword();
			String _md5 = DigestUtils.md5Hex(password);
			String _md5_md5 = DigestUtils.md5Hex(_md5);
			if (password.equals(user.getPassword()) || _md5.equals(user.getPassword())
					|| _md5_md5.equals(user.getPassword())) {
				return loginSuccess(user, example);
			}
			throw new ServiceException(1040102, "帐号密码错误");
		}
	}
	
	@Override
	public Map<String, Object> loginv1(UserExample example) {
		User user = userRepository.getUserv1(example.getTelephone(),example.getUserId(), null);
		if (null == user) {
			throw new ServiceException(1040101, "帐号不存在, 请重新注册!");
		}else if(!StringUtil.isEmpty(example.getRandcode())){
			//使用验证码登陆
			if(smsService.isAvailable(user.getTelephone(), example.getRandcode()))
				return loginSuccess(user, example);
			else throw new ServiceException(0, "验证码不正确");
			
		} else {
			String password = example.getPassword();
			String _md5 = DigestUtils.md5Hex(password);
			String _md5_md5 = DigestUtils.md5Hex(_md5);
			if (password.equals(user.getPassword()) || _md5.equals(user.getPassword())
					|| _md5_md5.equals(user.getPassword())) {
				return loginSuccess(user, example);
			}
			throw new ServiceException(1040102, "帐号密码错误");
		}
	}
	
	//登陆成功方法
	public  Map<String, Object> loginSuccess(User user,UserExample example){
		// 获取上次登录日志
		Object login = userRepository.getLogin(user.getUserId());
		// 保存登录日志
		userRepository.updateLogin(user.getUserId(), example);
		// f1981e4bd8a0d6d8462016d2fc6276b3
		Map<String, Object> data = userRepository.getAT(user.getUserId(), example.getTelephone());
		data.put("userId", user.getUserId());
		data.put("password", user.getPassword());
		data.put("nickname", user.getNickname());
		data.put("companyId", user.getCompanyId());
		data.put("login", login);
		
		Query<Friends> q = dsForRW.createQuery(Friends.class).field("userId").equal(user.getUserId());
		
		//好友关系数量
		data.put("friendCount", q.countAll());
		// 保存登录日志
		
		///检查该用户  是否注册到 Tigase
			examineTigaseUser(user.getUserId(), user.getPassword());
		return data;
	}
	

	@Override
	public Map<String, Object> loginAuto(String access_token, int userId, String serial,String appId) {
		
		User user = getUser(userId);
		 if (null == user) 
				throw new ServiceException(1040101, "帐号不存在, 请重新注册!");
		 
				 User.LoginLog loginLog = userRepository.getLogin(userId);
				boolean exists = jedisTemplate.execute(new JedisCallback<Boolean>() {
	
					@Override
					public Boolean execute(Jedis jedis) {
						String atKey = KKeyConstant.userIdKey(access_token);
						return jedis.exists(atKey);
					}
	
				});
			// 1=没有设备号、2=设备号一致、3=设备号不一致
			int serialStatus = null == loginLog ? 1 : (serial.equals(loginLog.getSerial()) ? 2 : 3);
			// 1=令牌存在、0=令牌不存在
			int tokenExists=exists ? 1 : 0;	
			
			try {

			Map<String, Object> result = Maps.newHashMap();
			result.put("serialStatus", serialStatus);
			result.put("tokenExists", tokenExists);
			result.put("userId", userId);
			result.put("nickname", user.getNickname());
			result.put("name", user.getName());
			result.put("login", loginLog);

			
			//更新appId
			updateAttributeByIdAndKey(userId, "appId", appId);
			return result;
		} catch (NullPointerException e) {
			throw new ServiceException("帐号不存在");
		} catch (Exception e) {
			throw new ServiceException(e.getMessage());
		}
	}

	@Override
	public void logout(String access_token,String areaCode,String userKey) {
		if(StringUtil.isEmpty(userKey)){
			Query<User> q = dsForRW.createQuery(User.class)
					.filter("areaCode", areaCode)
					.field("userKey")
					.equal(userKey);
			UpdateOperations<User> ops = dsForRW.createUpdateOperations(User.class);
			ops.set("active",DateUtil.currentTimeSeconds());
			ops.set("loginLog.offlineTime",DateUtil.currentTimeSeconds());
			dsForRW.findAndModify(q, ops);	
		}
		
		jedisTemplate.execute(new JedisCallbackVoid() {		
		 @Override
		 public void execute(Jedis jedis) {
		 String atKey = KKeyConstant.atKey(userKey);
		 String userIdKey = KKeyConstant.userIdKey(access_token);
		 jedis.del(atKey, userIdKey);
		 }
		 });
	}

	@Override
	public List<DBObject> query(UserQueryExample param) {
		return userRepository.queryUser(param);
	}

	@Override
	public Map<String, Object> register(UserExample example) {
		if (isRegister(example.getTelephone(),example.getNickname()))
			throw new ServiceException("手机号已被注册");

		// 生成userId
		Integer userId = idxManager.getUserId();
		// 新增用户
		Map<String, Object> data = userRepository.addUser(userId, example);

		if (null != data) {
			try {
				KXMPPServiceImpl.getInstance().registerByThread(userId.toString(), example.getPassword());
			} catch (Exception e) {
				e.printStackTrace();
			}
			try {
				NearbyUser userPoi = new NearbyUser();
				// userPoi.setAddress(address);
				userPoi.setBirthday(example.getBirthday());
				userPoi.setDescription(example.getDescription());
				// userPoi.setDistance(distance);
				userPoi.setLatitude(example.getLatitude());
				userPoi.setLongitude(example.getLongitude());
				userPoi.setNickname(example.getNickname());
				// userPoi.setPoiId(poiId);
				userPoi.setSex(example.getSex());
				// userPoi.setTags(tags);
				// userPoi.setTitle(title);
				userPoi.setUserId(userId);
				nearbyManager.saveUser(userPoi);
			} catch (Exception e) {
				e.printStackTrace();
			}

			if (null == example.getCompanyId() || 0 == example.getCompanyId()) {
				try {
					
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			return data;
		}
		throw new ServiceException("用户注册失败");
	}
	public boolean isRegister(String telephone,String  nickname){
		long count=dsForRW.createQuery(User.class).field("telephone")
				.equal(telephone).filter("nickname", nickname).countAll();
		if(0<count)
			return true;
		else return false;
	}
	@Override
	public Map<String, Object> registerIMUser(UserExample example) {
		if (isRegister(example.getTelephone(),example.getNickname()))
			throw new ServiceException("手机号已被注册");

		// 生成userId
		Integer userId = idxManager.getUserId();
		// 新增用户
		Map<String, Object> data = userRepository.addUser(userId, example);
		if (null != data) {
			try {
				KXMPPServiceImpl.getInstance().registerByThread(userId.toString(), example.getPassword());
			} catch (Exception e) {
				e.printStackTrace();
			}
			try {
				friendsManager.followUser(userId, 10000);
			} catch (Exception e) {
				e.printStackTrace();
			}
			return data;
		}
		throw new ServiceException("用户注册失败");
	}
	public List<User> getUsersByPhone(String telephone){
		return createQuery().filter("telephone", telephone).asList();
	}
	@Override
	public void resetPassword(String telephone, String password) {
		userRepository.updatePassword(telephone, password);
		KXMPPServiceImpl.getInstance().updateToTig(getUser(telephone).getUserId(), password);
	}

	@Override
	public void updatePassword(int userId, String oldPassword, String newPassword) {
		User user = getUser(userId);
		String _md5 = DigestUtils.md5Hex(oldPassword);
		String _md5_md5 = DigestUtils.md5Hex(_md5);

		if (oldPassword.equals(user.getPassword()) || _md5.equals(user.getPassword())
				|| _md5_md5.equals(user.getPassword())) {
			userRepository.updatePassowrd(userId, newPassword);
			KXMPPServiceImpl.getInstance().updateToTig(userId, newPassword);
		} else
			throw new ServiceException("旧密码错误");
	}

	@Override
	public User updateSettings(int userId,User.UserSettings userSettings) {		
		return userRepository.updateSettings(userId, userSettings);
	}

	@Override
	public User updateUser(int userId, UserExample param) {
		return userRepository.updateUser(userId, param);
	}
	public List<User> findUserList(int pageIndex, int pageSize,Integer notId) {
		Query<User> query=createQuery();
		List<Integer> ids=new ArrayList<Integer>(){{add(10000);add(10005);add(10006);add(notId);}};
		query.field("_id").notIn(ids);
		return query.order("-_id").offset(pageIndex * pageSize).limit(pageSize).asList();
	}
	
	@Override
	public List<DBObject> findUser(int pageIndex, int pageSize) {
		return userRepository.findUser(pageIndex, pageSize);
	}

	@Override
	public List<Integer> getAllUserId() {
		return dsForRW.getCollection((User.class)).distinct("_id");
	}

	@Override
	public void outtime(String access_token, int userId) {
		Query<User> q = dsForRW.createQuery(User.class).field("_id")
				.equal(userId);
		UpdateOperations<User> ops = dsForRW.createUpdateOperations(User.class);
		ops.set("active",DateUtil.currentTimeSeconds());
		ops.set("loginLog.offlineTime",DateUtil.currentTimeSeconds());
		dsForRW.findAndModify(q, ops);
	}

	@Override
	public void addUser(int userId, String password) {
		userRepository.addUser(userId, password);
	}

	/*@Override
	public User getfUser(int userId) {
		User user = userRepository.getUser(userId);
		if (null == user)
			return null;
		if (0 != user.getCompanyId())
			user.setCompany(companyManager.get(user.getCompanyId()));
			return user;		
	}*/
	
	//用户充值 type 1 充值  2 消费
	public Double rechargeUserMoeny(Integer userId,Double money,int type){
			try {
				Query<User> q =dsForRW.createQuery(User.class);
				q.field("_id").equal(userId);
				
				UpdateOperations<User> ops =dsForRW.createUpdateOperations(User.class);
				User user=KSessionUtil.getUserByUserId(userId);
				if(null==user)
					return 0.0;
				if(KConstants.MOENY_ADD==type){
					ops.inc("balance", money);
					ops.inc("totalRecharge",money);
					user.setBalance(user.getBalance()+money);
				}else{ 
					ops.inc("balance", -money);
					ops.inc("totalConsume",money);
					user.setBalance(user.getBalance()-money);
				}
				dsForRW.update(q, ops);
				KSessionUtil.saveUserByUserId(userId, user);
			return q.get().getBalance();
			} catch (Exception e) {
				e.printStackTrace();
				return 0.0;
			}
	}
		//用户充值 type 1 充值  2 消费
		public Double getUserMoeny(Integer userId){
				try {
					Query<User> q =dsForRW.createQuery(User.class);
					q.field("_id").equal(userId);
					
				return q.get().getBalance();
				} catch (Exception e) {
					e.printStackTrace();
					return 0.0;
				}
		}
		public int getOnlinestateByUserId(Integer userId) {
			DBObject q=new BasicDBObject("_id",userId);
			List<Object> states= distinct("onlinestate", q);
			if(states!=null&&states.size()>0)
				return (int)states.get(0);
			return 0;
		}
		
		
		public void examineTigaseUser(Integer userId,String password){
			new Thread(new Runnable() {
				
				@Override
				public void run() {
					try {
						DBObject q=new BasicDBObject("user_id",userId+"@"+xmppConfig.getHost());
						DBObject obj=dsForTigase.getDB().getCollection("tig_users").findOne(q);
						if(null==obj){
							KXMPPServiceImpl.getInstance().registerByThread(String.valueOf(userId), password);
						}
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
				}
			}).start();
			
			
		}

		@Override
		public User getUserByStudentIdOrTeacherId(Integer studentId,
				Integer teacherId) {
			if(studentId != null && teacherId != null){
				Query<User> q = dsForRW.createQuery(User.class).field("studentId").equal(studentId).field("teacherId").equal(teacherId);
				return q.get();
			}else if(studentId != null){
				Query<User> q = dsForRW.createQuery(User.class).field("studentId").equal(studentId);
				return q.get();
			}else if( teacherId != null){
				Query<User> q = dsForRW.createQuery(User.class).field("teacherId").equal(teacherId);
				return q.get();
			}
			return null;
		}
}
